package com.bsj.travel.mqtt.auth;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSON;
import com.bsj.travel.cached.redis.RedisCached;
import com.bsj.travel.config.rocketmq.producer.BaseMqPushUtil;
import com.bsj.travel.constant.ActConstants;
import com.bsj.travel.constant.BaseServerTopicConstants;
import com.bsj.travel.def.common.DO.DeviceDO;
import com.bsj.travel.def.common.DTO.mqtt.EventAct;
import com.bsj.travel.def.common.DTO.mqtt.NetworkEnum;
import com.bsj.travel.def.mqtt.auth.MqttSignature;
import com.bsj.travel.mqtt.RemoteMqttBrokerService;
import com.bsj.travel.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.iot.mqtt.core.server.auth.IMqttServerAuthHandler;
import net.dreamlu.mica.redis.cache.MicaRedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.tio.core.ChannelContext;
import org.tio.core.Node;

/**
 * @author yinhao
 * @version 1.0
 * @description 自定义mqtt认证
 * @date 2023/11/6
 */
@Slf4j
public class MqttAuthHandler implements IMqttServerAuthHandler {

    @Autowired
    private RedisCached redisCached;

    @Autowired
    private BaseMqPushUtil baseMqPushUtil;

    /**
     * 登录验证
     * @param channelContext 连接管道
     * @param uniqueId 唯一ID
     * @param clientId 客户端ID
     * @param userName 用户名称
     * @param password 密码
     * @desc 启用三元组鉴权模式
     *          clientId： productKey.deviceName|securemode=2,signmethod=hmacsha256,timestamp=1699345650774|
     *          username: deviceName&productKey
     *          password: deviceSecret HmacSHA256 encode
     * @return
     */
    @Override
    public boolean authenticate(ChannelContext channelContext, String uniqueId,
                                String clientId, String userName, String password) {
        Node clientNode = channelContext.getClientNode();
        long millis = System.currentTimeMillis();
        EventAct eventAct = EventAct.builder()
                .timestamp(millis)
                .traceId(RandomUtil.randomString(30))
                .serveType(2)
                .operate(ActConstants.CONNECT)
                .build();
        log.info("当前连接Ip： {} username: {} password: {}", clientNode.getIp(), userName, password);
        if (StringUtils.isNull(userName) || StringUtils.isNull(password)) {
            eventAct.setCode(NetworkEnum.MQTT_CONNECT_PASSWORD_FAIL.getCode());
            baseMqPushUtil.sendTopicBytes(BaseServerTopicConstants.TRAVEL_MQTT_MSG_PROCESS_TOPIC,
                    BaseServerTopicConstants.TRAVEL_MQTT_MSG_PROCESS_BEHAVIOR_TAG, JSON.toJSONBytes(eventAct));
            return false;
        }
        MqttSignature mqttAuth = new MqttSignature(clientId);
        //1.判断产品是否正确，2.判断设备信息是否正确 3.判断三元组是否正确
        String productKey = mqttAuth.getProductKey();
        String deviceName = mqttAuth.getDeviceName();
        String timestamp = mqttAuth.getTimestamp();
        if (productKey == null || deviceName == null || timestamp == null) {
            eventAct.setCode(NetworkEnum.MQTT_CONNECT_SECRET_NULL.getCode());
            baseMqPushUtil.sendTopicBytes(BaseServerTopicConstants.TRAVEL_MQTT_MSG_PROCESS_TOPIC,
                    BaseServerTopicConstants.TRAVEL_MQTT_MSG_PROCESS_BEHAVIOR_TAG, JSON.toJSONBytes(eventAct));
            return false;
        }
        boolean checkProductExists = redisCached.checkProductExists(productKey);
        if (!checkProductExists) {
            eventAct.setCode(NetworkEnum.MQTT_CONNECT_PRODUCT_FAIL.getCode());
            //无效产品信息
            baseMqPushUtil.sendTopicBytes(BaseServerTopicConstants.TRAVEL_MQTT_MSG_PROCESS_TOPIC,
                    BaseServerTopicConstants.TRAVEL_MQTT_MSG_PROCESS_BEHAVIOR_TAG, JSON.toJSONBytes(eventAct));
            return false;
        }
        DeviceDO deviceDO = redisCached.hgetDeviceInfo(productKey, deviceName);
        if (deviceDO == null) {
            //无效设备信息
            eventAct.setCode(NetworkEnum.MQTT_CONNECT_DEVICE_FAIL.getCode());
            baseMqPushUtil.sendTopicBytes(BaseServerTopicConstants.TRAVEL_MQTT_MSG_PROCESS_TOPIC,
                    BaseServerTopicConstants.TRAVEL_MQTT_MSG_PROCESS_BEHAVIOR_TAG, JSON.toJSONBytes(eventAct));
            return false;
        }
        if(deviceDO.getIsDisable() != null && deviceDO.getIsDisable() == 1) {
            //设备已被禁用
            eventAct.setCode(NetworkEnum.MQTT_CONNECT_DEV_STATUS_BAN.getCode());
            baseMqPushUtil.sendTopicBytes(BaseServerTopicConstants.TRAVEL_MQTT_MSG_PROCESS_TOPIC,
                    BaseServerTopicConstants.TRAVEL_MQTT_MSG_PROCESS_BEHAVIOR_TAG, JSON.toJSONBytes(eventAct));
            return false;
        }
        MqttSignature mqttSignature = new MqttSignature(productKey, deviceName, deviceDO.getDeviceSecret(), timestamp);
        boolean doMqttSign = mqttSignature.doMqttSign(clientId, userName, password);
        if (!doMqttSign) {
            //三元组错误,禁止连接
            eventAct.setCode(NetworkEnum.MQTT_CONNECT_TRIPLET_FAIL.getCode());
            baseMqPushUtil.sendTopicBytes(BaseServerTopicConstants.TRAVEL_MQTT_MSG_PROCESS_TOPIC,
                    BaseServerTopicConstants.TRAVEL_MQTT_MSG_PROCESS_BEHAVIOR_TAG, JSON.toJSONBytes(eventAct));
            return false;
        }
        //增加同设备互斥连接，只能有一个设备连接在线，直接在集群内广播，先将前面上线的踢掉，再进行上线操作
//        MqttServer mqttServer = SpringUtil.getBean(MqttServer.class);
//        doMqttConnectOffline(userName, mqttServer);
//        SendMqttMsg sendMqttMsg = SendMqttMsg.builder().username(userName).build();
//        JsonResult<Boolean> result = mqttBrokerService.mqttConnectTake(sendMqttMsg);
//        log.info("mqttConnectTake status: {}", result.getData());
        return true;
    }

//    @Override
//    public boolean verifyAuthenticate(ChannelContext context, String uniqueId, String clientId, String userName, String password) {
//        return false;
//    }
}
